package com.cis467.mrball;

import com.cis467.mrball.parts.Button;
import com.cis467.mrball.parts.Floor;
import com.cis467.mrball.parts.Level;
import com.cis467.mrball.parts.Menu;
import com.cis467.mrball.parts.Portal;
import com.cis467.mrball.parts.Wall;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;

public class BuildLevelScreenManager extends ScreenManager {
	
	// Menu constats
	public static final int NONE = -1;
	public static final int SPECIAL = 0;
	public static final int FLOOR = 1;
	public static final int WALL = 2;
	public static final int BUTTON = 3;
	public static final int PORTAL = 4;
	public static final int REMOVE = 5;
	
	// Removal constants
	public static final int REMOVE_HWALL = 0;
	public static final int REMOVE_VWALL = 1;
	public static final int REMOVE_FLOOR = 2;
	
	// Menu size constants
	private static final int NUM_MENU_OPTIONS = 6;
	private static final int NUM_ITEM_CONTAINERS = 4;
	
	// For centering walls within item previews
	private int mWallOffset;
	
	// Side panel dimensions
	private int mMenuOptionHeight;
	private int mMenuTextWidthOffset;
	private int mMenuTextHeightOffset;
	
	// Bottom panel dimensions
	private int mBottomPanelOffset;
	private int mItemContainerWidth;
	private int mItemWidthOffset;
	private int mItemHeightOffset;
	
	// List of menus
	private Menu[] menus;
		
	public BuildLevelScreenManager (Context context, double w2tRatio) {
		
		super(context, false);
		
		buildMenus();		
	}
	
	private void buildMenus() {
		
		menus = new Menu[NUM_MENU_OPTIONS];
		
		// Build the special menu
		menus[SPECIAL] = new Menu("Special");
		menus[SPECIAL].add(mImageManager.start);
		menus[SPECIAL].add(mImageManager.key);
		menus[SPECIAL].add(mImageManager.end);
				
		// Build the floors menu
		menus[FLOOR] = new Menu("Floors");
		menus[FLOOR].add(mImageManager.floors[Floor.PIT]);
		menus[FLOOR].add(mImageManager.floors[Floor.SLOW]);
		menus[FLOOR].add(mImageManager.floors[Floor.NORMAL]);
		menus[FLOOR].add(mImageManager.floors[Floor.FAST]);
		
		// Build the walls menu
		menus[WALL] = new Menu("Walls");
		menus[WALL].add(mImageManager.menuHWalls[Wall.NORMAL]);
		menus[WALL].add(mImageManager.menuVWalls[Wall.NORMAL]);
		menus[WALL].add(mImageManager.menuHWalls[Wall.LASER]);
		menus[WALL].add(mImageManager.menuVWalls[Wall.LASER]);
		
		// Build the buttons menu
		menus[BUTTON] = new Menu("Buttons");
		menus[BUTTON].add(mImageManager.buttons[Button.RED]);
		menus[BUTTON].add(mImageManager.buttons[Button.GREEN]);
		menus[BUTTON].add(mImageManager.buttons[Button.BLUE]);
		menus[BUTTON].add(mImageManager.buttons[Button.YELLOW]);
		
		// Build the portals menu
		menus[PORTAL] = new Menu("Portals");
		menus[PORTAL].add(mImageManager.portals[Portal.RED]);
		menus[PORTAL].add(mImageManager.portals[Portal.GREEN]);
		menus[PORTAL].add(mImageManager.portals[Portal.BLUE]);
		menus[PORTAL].add(mImageManager.portals[Portal.YELLOW]);
		
		// Build the remove menu
		menus[REMOVE] = new Menu("Remove");
		menus[REMOVE].add(mImageManager.menuHWalls[Wall.NORMAL]);
		menus[REMOVE].add(mImageManager.menuVWalls[Wall.NORMAL]);
		menus[REMOVE].add(mImageManager.floors[Floor.NORMAL]);
	}
	
	public void setDimensions(int width, int height) {
		
		super.setDimensions(width, height);
		
		// Rebuild the menus
		buildMenus();

		// Set up side panel dimensions
		mMenuOptionHeight = (mScreenHeight - (mTileSize + 4*MENU_BUFFER)) / NUM_MENU_OPTIONS;
		mMenuTextWidthOffset = mSidePanelWidth / 10;
		mMenuTextHeightOffset = mMenuOptionHeight/2 + SharedConstants.NORMAL_TEXT_SIZE/3;
		
		// Set up top panel dimensions
		mBottomPanelOffset = mMenuOptionHeight * NUM_MENU_OPTIONS - MENU_BUFFER;
		mItemContainerWidth = (mScreenWidth - mSidePanelWidth) / NUM_ITEM_CONTAINERS;
		mItemWidthOffset = mItemContainerWidth/2 - mTileSize/2;
		mItemHeightOffset = (mScreenHeight - mBottomPanelOffset)/2 - mTileSize/2;
		
		// Set the centering offset for walls
		mWallOffset = (mTileSize - mImageManager.menuHWalls[Wall.NORMAL].getHeight()) / 2;
		
	}
	
    public void draw(Canvas canvas, Level pLevel, int activeMenu, int itemMenu, int itemNum) {

    	this.canvas = canvas;
    	
    	clearCanvas();
    	
    	renderLevel(pLevel);
    	
    	drawStatic();
    	
    	drawAllDynamic(pLevel);
    	
    	drawSidePanel(activeMenu, itemMenu, itemNum);
    	
    	if(activeMenu != NONE)
    		drawBottomPanel(activeMenu);
    }

	public void drawSidePanel(int activeMenu, int itemMenu, int itemNum) {
		
		// Draw the main panel box
        canvas.drawRect(mSidePanelOffset, 0, mScreenWidth, mScreenHeight, mPaintManager.getPaint(PaintManager.PANEL));
      
        // For each menu option
        for(int i = 0; i < NUM_MENU_OPTIONS; i++) {
        	
        	// Draw the individual container
        	canvas.drawRect(mSidePanelOffset + MENU_BUFFER, 
        					i * mMenuOptionHeight + MENU_BUFFER, 
        					mScreenWidth - MENU_BUFFER, 
        					(i+1) * mMenuOptionHeight - MENU_BUFFER, 
        					mPaintManager.getPaint(PaintManager.CONTAINER));
        	
        	// Set up the text parameters
        	String label = menus[i].name;
        	int xPos = mSidePanelOffset + mMenuTextWidthOffset;
        	int yPos = i*mMenuOptionHeight + mMenuTextHeightOffset;
        	Paint paint;
        	
        	if(i == activeMenu) 
        		paint = mPaintManager.getPaint(PaintManager.TEXT_ACTIVE);
        	else
        		paint = mPaintManager.getPaint(PaintManager.TEXT_NORMAL);
        	
        	// Draw the text
        	canvas.drawText(label, xPos, yPos, paint);
        }
        
        Paint containerColor;
        
        if(itemMenu == REMOVE)
        	containerColor = mPaintManager.getPaint(PaintManager.REMOVE);
        else
        	containerColor = mPaintManager.getPaint(PaintManager.SELECTED);
        
        // Draw the selected item container
    	canvas.drawRect(mSidePanelOffset + MENU_BUFFER, 
				mBottomPanelOffset + 2*MENU_BUFFER, 
				mScreenWidth - MENU_BUFFER, 
				mScreenHeight - MENU_BUFFER, 
				containerColor);
    	
    	// Check if there is a selected item to draw
    	if(itemNum != NONE)
    		drawItem(itemMenu, itemNum, 
    			mSidePanelOffset + mItemWidthOffset, mBottomPanelOffset + mItemHeightOffset);
    		

	}
	
	public void drawBottomPanel(int activeMenu) {
		
		// Draw the main panel box
        canvas.drawRect(0, mBottomPanelOffset, mSidePanelOffset, mScreenHeight, mPaintManager.getPaint(PaintManager.PANEL));
      
        // Draw the item containers
        for(int i = 0; i < NUM_ITEM_CONTAINERS; i++) {
        	
        	Paint containerColor;
        
        	if(activeMenu == REMOVE)
        		containerColor = mPaintManager.getPaint(PaintManager.REMOVE);
        	else
        		containerColor = mPaintManager.getPaint(PaintManager.CONTAINER);
        	
        	canvas.drawRect(i * mItemContainerWidth + MENU_BUFFER, 
        					mBottomPanelOffset + 2*MENU_BUFFER, 
        					(i+1)* mItemContainerWidth - MENU_BUFFER, 
        					mScreenHeight - MENU_BUFFER, 
        					containerColor);
        }
        
        // Draw the item images
        for(int i = 0; i < menus[activeMenu].menuItems.size(); i++) {
        	
        	// Determine the position of the menu item
        	int xPos = i*mItemContainerWidth + mItemWidthOffset;
        	int yPos = mBottomPanelOffset + mItemHeightOffset;
        	
        	// Draw it
        	drawItem(activeMenu, i, xPos, yPos);
        }
	}
	
	private void drawItem(int itemMenu, int itemNum, int x, int y) {
		
		// Get the item's image
		Bitmap image = menus[itemMenu].menuItems.get(itemNum);
		
		// Check if we need to draw a base image
		if(itemMenu != FLOOR) {
        	
			// Get a normal base image
    		Bitmap under = menus[FLOOR].get(Floor.NORMAL);
    		
        	// Draw the base image
        	canvas.drawBitmap(under, x, y, null);
        	
        	// Center the wall images
        	if((itemMenu == WALL && itemNum % 2 == 1) || (itemMenu == REMOVE && itemNum == 1))
        		x += mWallOffset;
        	
        	else if((itemMenu == WALL && itemNum % 2 == 0) || (itemMenu == REMOVE && itemNum == 0))
        		y += mWallOffset;
    	}
    	
    	// Draw the top image
    	canvas.drawBitmap(image, x, y, null);
	}
	
	public boolean isSideMenuTouch(int x) {
		
		return x >= mSidePanelOffset;
	}
	
	public boolean isBottomMenuTouch(int x, int y) {
		
		return x < mSidePanelOffset && y > mBottomPanelOffset;
	}
	
	public int resolveSideMenuTouch(int y) {
		
		if(y > mMenuOptionHeight * NUM_MENU_OPTIONS)
			return NONE; // Selected item register as NONE
		else 
			return y / mMenuOptionHeight;
	}
	
	public int resolveBottomMenuTouch(int x, int menu) {
		
		if((menu == SPECIAL || menu == REMOVE) && x / mItemContainerWidth > 2)
			return NONE; // there is no forth item
		
		if(x > mItemContainerWidth * NUM_ITEM_CONTAINERS)
			return NONE; // Just in case
		
		return x / mItemContainerWidth;
	}
	
	public int resolveLevelCol(int x, int itemMenu, int itemNum) {
		
		// Handle vertical walls differently
		if((itemMenu == WALL && itemNum % 2 == 1) || (itemMenu == REMOVE && itemNum == REMOVE_VWALL)) {
			
			// Get the actual column
			int col = (x + mTileSize/2) / mTileSize;
			
			// Borders can't be selected
			if(col <= 0)
				col = 1;
			else if(col >= Level.VWALL_COLS - 1)
				col = Level.VWALL_COLS -2;
			
			return col;
		}
		
		// Handle everything else the same
		else {
			
			int col = (x - mOffsetWidth ) / mTileSize;
			
			// Make sure we aren't out of bounds
			if(col <= 0)
				col = 0;
			else if(col >= Level.FLOOR_COLS)
				col = Level.FLOOR_COLS-1;
			
			return col;
		}
	}
	
	public int resolveLevelRow(int y, int itemMenu, int itemNum) {
		
		// Handle horizontal walls differently
		if((itemMenu == WALL && itemNum % 2 == 0) || (itemMenu == REMOVE && itemNum == REMOVE_HWALL)) {
			
			// Get the actual column
			int row = (y + mTileSize/2) / mTileSize;
			
			// Borders can't be selected
			if(row <= 0)
				row = 1;
			else if(row >= Level.HWALL_ROWS - 1)
				row = Level.HWALL_ROWS -2;
			
			return row;
		}
		
		// Handle everything else the same
		else {
			
			int row = (y - mOffsetHeight ) / mTileSize;
			
			// Make sure we aren't out of bounds
			if(row <= 0)
				row = 0;
			else if(row >= Level.FLOOR_ROWS)
				row = Level.FLOOR_ROWS-1;
			
			return row;
		}
	}
}